package com.xcdh.ittools.sql;

import com.xcdh.ittools.mapping.ITToolParameterMapping;
import com.xcdh.ittools.parsing.ITToolDynamicTokenParser;
import com.xcdh.ittools.parsing.ITToolTokenParser;
import org.apache.ibatis.parsing.GenericTokenParser;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;

import java.util.ArrayList;
import java.util.List;

public class ITToolBoundSql {
    private final String sql ;
    private final Object parameter ;
    private final Configuration configuration ;

    private final ITToolTokenParser tokenParser ;
    private List<ITToolParameterMapping> parameterMappings = new ArrayList<>();

    public ITToolBoundSql(Configuration configuration , String sql , Object parameter){
        this.sql = sql ;
        this.parameter = parameter ;
        this.configuration = configuration ;
        this.tokenParser = new ITToolTokenParser() ;
    }

    public List<ITToolParameterMapping> getParameterMappings(){
        return parameterMappings ;
    }

    private  String dynamicParse (String sql){
        ITToolDynamicTokenParser dynamicTokenParser = new ITToolDynamicTokenParser(parameter , null) ;
        GenericTokenParser genericTokenParser = new GenericTokenParser("${","}",dynamicTokenParser);
        return genericTokenParser.parse(sql);
    }

    private String sqlParse(String sql){
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{","}",tokenParser);
        return genericTokenParser.parse(sql);
    }

    public String  getSql(){
        String sql = dynamicParse(this.sql);
        sql = sqlParse(sql) ;
        buildParameterMapping();
        return sql ;
    }

    private void buildParameterMapping(){
        List<String> names = tokenParser.getNames();
        parameterMappings.clear();
        MetaObject metaObject = configuration.newMetaObject(parameter);
        for (String name : names) {
            final Class<?> propertyType = metaObject.getSetterType(name);
            TypeHandler<?> typeHandler = configuration.getTypeHandlerRegistry().getTypeHandler(propertyType);
            parameterMappings.add(new ITToolParameterMapping(name , typeHandler ,metaObject.getValue(name)));
        }
    }
}
